fix(mobile): bind same-name mentions to exact selected identities - #7385
fix(mobile): bind same-name mentions to exact selected identities#7385loganj wants to merge 5 commits into
Conversation
Signed-off-by: Logan Johnson <loganj@squareup.com>
🔐 Codex Security Review
|
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
|
@buzz-security-review 39afd73 |
Independent exact-mention readiness evidence — 2026-09-07Verified current range:
2026-09-07 update: the stale composed reference described above has been retired — the |
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — REQUEST CHANGES on exact head 39afd73b0adfde14164f4b10dbd089cb498312b6 (base 3c7f288c60d67df78577b237e27c3dfc8831aaa1).
Two exact-identity failures remain:
-
Persisted drafts discard selected identities.
ComposeBarkeeps selection ownership only in its in-memorymentionMap(mobile/lib/features/channels/compose_bar/compose_bar_widget.dart:219-226), whileComposeDraftpersists/restores text only (mobile/lib/features/activity/compose_drafts_provider.dart:18-40,104-143). After teardown/restart, sending reconstructs recipients from current member names (compose_bar_widget.dart:486-503). Two independent production-widget reproductions selected same-name recipients, unmounted/remounted against the persisted store, and then found Send never reachedonSend: the restored plain@Scouthad become ambiguous. The UI preserves exact-looking text while silently losing authored identity intent.Required: persist and hydrate exact bindings atomically with draft text in this PR (or absorb the relevant stacked persistence work), and add teardown/restart → restore → send coverage including profile/roster changes and malformed/legacy state. A follow-up PR does not make this merge commit safe.
-
Renaming the unqualified recipient retargets their rendered chip.
renderedMentionBindingsderives aliases from current profile names (mobile/lib/shared/mentions/mention_bindings.dart:67-70) and uses the qualified occurrence only to subtract its key (:98-109); it never assigns the remaining tagged identity to the historical unqualified occurrence. For authored@Scout @Scout (<second key>)with signed recipients{first: "Renamed Scout", second: "Scout"}, an executable adversarial test expected the plain chip to bindfirstbut observed it bindsecond, so both visible chips target the second person. Signedptags remain correct, but tapping the first mention opens the wrong profile, contradicting the PR’s stated rename behavior.Required: reconstruct unqualified occurrence ownership deterministically from event-tagged identities after exact qualified labels claim their keys. Add production-widget tap regressions for each recipient renaming independently, reversed tag order, missing profiles, and ambiguous leftovers.
Validation at the pinned head:
just mobile-test— 2,081 passed, exit 0, clean tree before/after.- Focused mention/content/composer tests — 122 passed, exit 0; a production-call mutation was caught by the relevant selection test.
git diff --checkclean; required CI green.
Confidence gap, not additional author action: no native iOS/Android keyboard, VoiceOver/TalkBack, theme, or navigation journey was observed. Exact-head advisory security automation produced no verdict; required CI is green.
🤖
Summary
If two people in a channel share a display name, mobile couldn't tell them apart in mentions: picking the second could overwrite the first's selection, a rendered mention linked whichever same-name person matched first, and a later rename or a shorter name could re-bind the text to the wrong recipient. This PR binds every mention to the exact selected identity:
Name (key…).Ports the landed Desktop exact-recipient behavior (see
docs/mention-editor.md).Related issue
main). fix(mobile): preserve exact mention recipients in saved drafts #7387 (child) persists these exact selections in saved drafts.Testing
just mobile-check, the full mobile test suite, and full localjust ciall pass — receipts in the exact-head evidence comment.To see it: mention two teammates with the same display name — both stay distinct, the second shows a qualified label, and the rendered message keeps both correct even after either renames.
Screenshots
Flutter production-widget test renders — not native-device screenshots or acceptance captures.
Capture provenance
Rendered by the Flutter widget engine in a
flutter testrun (production widgets, production theme; no device or simulator). Before: this PR's declared base3c7f288c60d67df78577b237e27c3dfc8831aaa1. After: its head39afd73b0adfde14164f4b10dbd089cb498312b6.